﻿<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../helpproject.xsl" ?>
<topic template="Default" lasteditedby="Geert" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../helpproject.xsd">
  <title translate="true">ViewModelLocator</title>
  <keywords>
    <keyword translate="true">IViewModelLocator</keyword>
    <keyword translate="true">ResolveViewModel</keyword>
    <keyword translate="true">ViewModelLocator</keyword>
  </keywords>
  <body>
    <header>
      <para styleclass="Heading1"><text styleclass="Heading1" translate="true">ViewModelLocator</text></para>
    </header>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">Starting with Catel 3.0, there are several ways to hook up a view model to the view. When a view is constructed, an MVVM behavior is added to the view. Thanks to these </text><link displaytype="text" defaultstyle="true" type="topiclink" href="MVVM_behaviors" styleclass="Normal" translate="true">MVVM behaviors</link><text styleclass="Normal" translate="true">, it is possible to use exactly the same logic on 3rd party controls.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Resolving by GetViewModelType() method</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">The first thing the view does is call the virtual </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Windows_Controls_UserControl_GetViewModelType" styleclass="Normal" translate="true">GetViewModelType</link><text styleclass="Normal" translate="true"> method. This method returns </text><text styleclass="Normal" style="font-style:italic;" translate="true">null</text><text styleclass="Normal" style="font-style:normal;" translate="true"> by default, but it is possible to override this. For example, to let a view know what view model it should use, the following code can be used:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">public</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">class</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">MyView</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">:</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">Catel.Windows.Controls.UserControl</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">{</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> &#160; &#160;</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">protected</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">override</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">Type</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">GetViewModelType()</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> &#160; &#160;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">{</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> &#160; &#160; &#160; &#160;</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">return</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">typeof</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">(MyCustomViewModel);</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> &#160; &#160;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">}</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">}</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-style:normal;" translate="true">Using this way, the view will use the </text><text styleclass="Normal" style="font-style:italic;" translate="true">MyCustomViewModel</text><text styleclass="Normal" style="font-style:normal;" translate="true"> as a view model.</text></para>
    <para styleclass="Notes"><text styleclass="Notes" translate="true">Note that the while using the conventions, magic words such as &quot;View&quot;, &quot;Control&quot;, &quot;UserControl&quot;, &quot;Window&quot; and &quot;Page&quot; will be stripped from the view name while locating the view model type</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Resolving by naming convention</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">If the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Windows_Controls_UserControl_GetViewModelType" styleclass="Normal" translate="true">GetViewModelType</link><text styleclass="Normal" translate="true"> method returns </text><text styleclass="Normal" style="font-style:italic;" translate="true">null</text><text styleclass="Normal" style="font-style:normal;" translate="true"> (which is the default behavior), the view will resolve the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_MVVM_IViewModelLocator" styleclass="Normal" style="font-style:normal;" translate="true">IViewModelLocator</link><text styleclass="Normal" style="font-style:normal;" translate="true"> from the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_IoC_ServiceLocator" styleclass="Normal" style="font-style:normal;" translate="true">ServiceLocator</link><text styleclass="Normal" style="font-style:normal;" translate="true">. Then it will use the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_MVVM_IViewModelLocator_ResolveViewModel_1_61b1ab37" styleclass="Normal" style="font-style:normal;" translate="true">ResolveViewModel</link><text styleclass="Normal" style="font-style:normal;" translate="true"> method to resolve the view model based on the type of the view.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-style:normal;" translate="true">For example, the following view:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">Catel.Examples.Views.MyView</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-style:normal;" translate="true">will be resolved as:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">Catel.Examples.ViewModels.MyViewModel</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Manually resolving a naming convention</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">To manually resolve a naming convention, use the following code:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">var</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">viewModelLocator</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">=</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">ServiceLocator.Instance.ResolveType&lt;IViewModelLocator&gt;();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">var viewModelType = viewModelLocator.ResolveViewModel(typeof(MyView));</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Customizing naming conventions</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">By default, the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_MVVM_IViewModelLocator" styleclass="Normal" style="font-style:normal;" translate="true">IViewModelLocator</link><text styleclass="Normal" style="font-style:normal;" translate="true"> uses the following naming conventions to resolve view models:</text></para>
    <list id="9" type="ul" listtype="bullet" formatstring="&#183;" format-charset="SYMBOL_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Symbol; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[UP].ViewModels.[VW]ViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[UP].ViewModels.[VW]ControlViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[UP].ViewModels.[VW]WindowViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[UP].ViewModels.[VW]PageViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[AS].ViewModels.[VW]ViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[AS].ViewModels.[VW]ControlViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[AS].ViewModels.[VW]WindowViewModel</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">[AS].ViewModels.[VW]PageViewModel</text></li>
    </list>
    <para styleclass="Notes"><text styleclass="Notes" translate="true">For more information, see </text><link displaytype="text" defaultstyle="true" type="topiclink" href="MVVM_Naming_conventions" styleclass="Notes" translate="true">naming conventions</link></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">However, it is possible to add or remove new naming conventions to support your own naming convention. For example, to add a new naming convention for a different assembly, use this code:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">var</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">viewModelLocator</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">=</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">ServiceLocator.Instance.ResolveType&lt;IViewModelLocator&gt;();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">viewModelLocator.NamingConventions.Add(&quot;MyCustomAssembly.ViewModels.[VW]ViewModel&quot;);</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Registering custom view models</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">Sometimes, a class doesn&apos;t follow a naming convention (for whatever reason possible). In such a case, it is possible to register a mapping manually using the following code:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">var</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">viewModelLocator</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">=</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true">&#32;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">ServiceLocator.Instance.ResolveType&lt;IViewModelLocator&gt;();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">viewModelLocator.Register(typeof(MyViewNotFollowingNamingConvention), typeof(MyViewModel));</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Using a custom ViewModelLocator</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">If you want to have total freedom to determine which view model is provided per view (maybe there are other services that have an impact on this), it is possible to create a custom </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_MVVM_IViewModelLocator" styleclass="Normal" style="font-style:normal;" translate="true">IViewModelLocator</link><text styleclass="Normal" style="font-style:normal;" translate="true"> implementation. Then the only thing to do is to register it using the following code:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">ServiceLocator.Instance.Register&lt;IViewModelLocator, MyViewModelLocator&gt;();</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Using a generic implementation of the view</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">Last but not least, it is still possible to use the &quot;old-fashioned&quot; way by using the generic view bases. These classes directly derive from the non-generic views and return the generic type definition of the view model using the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Windows_Controls_UserControl_GetViewModelType" styleclass="Normal" translate="true">GetViewModelType</link><text styleclass="Normal" translate="true"> method.</text></para>
  </body>
</topic>
